<?php

declare(strict_types=1);

namespace App\Controller\Webhook;

use App\Repository\WebhookRepository;
use App\Repository\WebhookRequestRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Yiisoft\DataResponse\Formatter\HtmlDataResponseFormatter;
use Yiisoft\Http\Status;
use Yiisoft\Router\CurrentRoute;
use Yiisoft\Router\UrlGeneratorInterface;
use Yiisoft\Yii\View\Renderer\ViewRenderer;

use function is_numeric;

final readonly class ShowAction
{
    public function __construct(
        private ViewRenderer $viewRenderer,
        private WebhookRepository $webhooks,
        private WebhookRequestRepository $requests,
        private UrlGeneratorInterface $urlGenerator,
        private CurrentRoute $currentRoute,
        private HtmlDataResponseFormatter $htmlFormatter,
    ) {}

    public function __invoke(ServerRequestInterface $request): ResponseInterface
    {
        $token = $this->currentRoute->getArgument('token');

        if ($token === null) {
            return $this->viewRenderer
                ->render('@src/Handler/NotFound/template')
                ->withStatus(Status::NOT_FOUND);
        }

        $webhook = $this->webhooks->findByToken($token);

        if ($webhook === null) {
            return $this->viewRenderer
                ->render('@src/Handler/NotFound/template')
                ->withStatus(Status::NOT_FOUND);
        }

        $requestList = $this->requests->listForWebhook($webhook['id']);
        $selectedRequestId = $this->resolveSelectedRequestId($request->getQueryParams(), $requestList);
        $selectedRequest = $selectedRequestId === null
            ? null
            : $this->requests->find($webhook['id'], $selectedRequestId);

        $uri = $request->getUri();
        $scheme = $uri->getScheme() ?: 'http';
        $host = $uri->getHost();
        $port = $uri->getPort();
        if ($port !== null && $port !== 80 && $port !== 443) {
            $host .= ':' . $port;
        }

        $captureUrl = $this->urlGenerator->generateAbsolute(
            'webhook.capture',
            ['token' => $webhook['token']],
            [],
            null,
            $scheme,
            $host === '' ? null : $host,
        );

        return $this->viewRenderer
            ->render(
                __DIR__ . '/show',
                [
                    'webhook' => $webhook,
                    'requests' => $requestList,
                    'selectedRequest' => $selectedRequest,
                    'captureUrl' => $captureUrl,
                ],
            )
            ->withResponseFormatter($this->htmlFormatter);
    }

    /**
     * @param array<string, mixed> $queryParams
     * @param list<array{id:int}> $requestList
     */
    private function resolveSelectedRequestId(array $queryParams, array $requestList): ?int
    {
        $requested = $queryParams['request'] ?? null;

        if (is_numeric($requested)) {
            return (int) $requested;
        }

        return $requestList[0]['id'] ?? null;
    }
}
